#ifndef ANIMATION_H
#define ANIMATION_H

#include <QWidget>
#include<QCoreApplication>
#include <QTimer>
#include <QFont>
#include <QObject>

#include <iostream>
#include <vector>
using namespace std;

typedef struct{
    int x,y;
    int w,h;
    int font_size;
    QWidget *subw;
}WidgetInfo;

#define SHOW_TIME 2000  //animation time
#define STEP_NUM 1000   //animation action number

#define MAX_SPEED 4     //start time is more quick
#define MIN_SPEED 1   //end time is  slower
#define FORMULA(x) (x*x*x)

class WidgetAnimation: public QObject
{
    Q_OBJECT

public:

    //window parameters
    int px,py;
    //animation parameters
    double stepx;
    double stepy;
    double stepw;
    double steph;

    //animation showed action number
    double showTimes;

    //window information
    WidgetInfo win_info;
    QWidget *win;

    //sub widgets information
    vector<WidgetInfo> parts;

    //timers
    QTimer *start_timer;
    QTimer *close_timer;

public:

    void init_win(QWidget *w)
    {
        win=w;
        setInfo(w,win_info);
    }

    void init_timer()
    {
        start_timer = new QTimer(this);
        QObject::connect(start_timer, SIGNAL(timeout()), this, SLOT(expand_window()));

        close_timer = new QTimer(this);
        connect(close_timer, SIGNAL(timeout()), this, SLOT(narrow_window()));
    }

    void init_place(int x, int y, double rx1,double ry1)
    {
        px=x,py=y;
        stepx=(-1.0*win_info.w*rx1)/STEP_NUM;
        stepy=(-1.0*win_info.h*ry1)/STEP_NUM;
        stepw=1.0*win_info.w/STEP_NUM;
        steph=1.0*win_info.h/STEP_NUM;
    }

    void add_showTimes()    //update speed
    {
        double k=MIN_SPEED-MAX_SPEED;
        k=k/FORMULA(STEP_NUM);

        double step=k*FORMULA(showTimes)+MAX_SPEED;
        showTimes+=step;
    }

    void sub_showTimes()  //update speed
    {
        double k=MIN_SPEED-MAX_SPEED;
        k=k/FORMULA(STEP_NUM);

        double step=k*FORMULA(showTimes)+MAX_SPEED;
        showTimes-=step;
    }

    void setInfo(QWidget *w, WidgetInfo &info)    //initial information
    {
        info.x=w->x();
        info.y=w->y();
        info.w=w->width();
        info.h=w->height();
        info.font_size=w->font().pointSize();
    }

    void addInfo(QWidget *w)    //initial information
    {
        WidgetInfo info;
        info.subw=w;
        info.x=w->x();
        info.y=w->y();
        info.w=w->width();
        info.h=w->height();
        info.font_size=w->font().pointSize();
        parts.push_back(info);
    }


    void update_parts(double ratio)    //update sub widgets
    {
        for(int i=0;i<parts.size();i++)
        {
            update_part(parts[i].subw,ratio,parts[i]);
        }
    }

    void update_part(QWidget *w, double ratio, WidgetInfo info) //update sub widget
    {
        w->setGeometry(info.x*ratio,info.y*ratio,info.w*ratio,info.h*ratio);
        QFont font=w->font();
        font.setPointSize(info.font_size*ratio);
        w->setFont(font);
    }

    void start_show()  //show
    {
        showTimes=0;
        close_timer->stop();
        start_timer->start(SHOW_TIME/STEP_NUM);
    }

    void close_show()  //close
    {
        start_timer->stop();
        close_timer->start(SHOW_TIME/STEP_NUM);
    }

public slots:
    void expand_window()
    {
        int x=px+stepx*showTimes;
        int y=py+stepy*showTimes;
        int w=showTimes*stepw;
        int h=showTimes*steph;
        win->setGeometry(x,y,w,h);
        win->show();

        update_parts(showTimes/STEP_NUM);

        add_showTimes();
        if(showTimes>STEP_NUM)
        {
            start_timer->stop();
        }
    }
    void narrow_window()
    {
        int x=px+stepx*showTimes;
        int y=py+stepy*showTimes;
        int w=showTimes*stepw;
        int h=showTimes*steph;
        win->setGeometry(x,y,w,h);

        update_parts(showTimes/STEP_NUM);

        sub_showTimes();
        if(showTimes<=0)
        {
            close_timer->stop();
            win->close();
        }
    }

};



#endif // ANIMATION_H
